'use strict'
const BaseService = require('./base')
const ResponseUtil = require('../utils/ResponseUtil');
const StringUtil = require('../utils/StringUtil');
const HelperUtil = require('../utils/HelperUtil');
const moment = require('moment');
const BigNumber = require('bignumber.js');
const crypto = require('crypto');
const MailUtil = require('../utils/MailUtil');
const cos = require('../utils/cos');
const fs = require('fs');
const AWS = require('aws-sdk');

let s3Client = null;

let s3ClientPublic = null;


class UploadService extends BaseService {

    getS3Client() {
        if (s3Client) {
            return s3Client;
        }
        const s3 = new AWS.S3({
            apiVersion: '2006-03-01',
            accessKeyId: this.app.config.s3['access-key-id'],
            secretAccessKey: this.app.config.s3['access-key-secret'],
            region: this.app.config.s3['region'],
            // endpoint:'https://s3.us-east-1.amazonaws.com'
        });
        return s3;
    }

    getS3ClientPublic() {
        if (s3ClientPublic) {
            return s3ClientPublic;
        }
        const s3 = new AWS.S3({
            apiVersion: '2006-03-01',
            accessKeyId: this.app.config.s3['access-key-id'],
            secretAccessKey: this.app.config.s3['access-key-secret'],
            region: this.app.config.s3['region-public'],
            // endpoint:'https://s3.us-east-1.amazonaws.com'
        });
        return s3;

    }

    async _uploadImageFun(filepath, key, mime) {
        let self = this;
        return new Promise(function (resolve, reject) {
            let s3 = self.getS3Client();
            fs.readFile(filepath, function (err, buf) {
                if (err) {
                    reject(err);
                } else {
                    let params = {Bucket: self.app.config.s3['bucket-name'], Key: key, Body: buf};
                    if (mime) {
                        params.ContentType = mime;
                    }
                    s3.upload(params, function (err, data) {
                        if (err) {
                            reject(err);
                        } else {
                            resolve(data);
                        }
                    });
                }
            })
        })
    }


    async _uploadImagePublicFun(filepath, key, mime) {
        let self = this;
        return new Promise(function (resolve, reject) {
            let s3 = self.getS3ClientPublic();
            fs.readFile(filepath, function (err, buf) {
                if (err) {
                    reject(err);
                } else {
                    let params = {Bucket: self.app.config.s3['bucket-name-public'], Key: key, Body: buf};
                    if (mime) {
                        params.ContentType = mime;
                    }
                    s3.upload(params, function (err, data) {
                        if (err) {
                            reject(err);
                        } else {
                            resolve(data);
                        }
                    });
                }
            })
        })
    }


    __getFileName(prefix, filename,filepath) {
        let suffix = '';
        if (filename) {
            let arr = filename.split('.');
            if (arr && arr.length === 2) {
                suffix = arr[1];
            }
        }

        if (prefix) {
            let fileName = prefix + "/" + moment().format('YYYY-MM-DD') + "-" + StringUtil.getUUID();

            if (["png", "jpg", "jpeg", "gif"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'image/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["mp4", "wav", "avi"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'video/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["zip", "rar", "7z"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'archive/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["pdf"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'document/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }

            return fileName;
        } else {

            let fileName = moment().format('YYYY-MM-DD') + "-" + StringUtil.getUUID();

            if (["png", "jpg", "jpeg", "gif"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'image/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["mp4", "wav", "avi"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'video/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["zip", "rar", "7z"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'archive/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }
            if (["pdf"].includes(filepath.split(".").slice(-1)[0])) {
                fileName = 'document/' + fileName + "." + filepath.split(".").slice(-1)[0]
            }

            return fileName;
        }
    }


    async uploadFile(prefix) {
        try {

            let files = this.ctx.request.files;

            if (!files || !(Array.isArray(files)) || !files[0].filepath) {
                return ResponseUtil.retArgErr();
            }
            let filepath = files[0].filepath;
            let filename = files[0].filename;
            let mime = files[0].mime;
            if (!mime) {
                mime = files[0].mimeType;
            }
            let name = this.__getFileName(prefix, filename,filepath);
            let result = await this._uploadImageFun(filepath, name, mime);
            return this.app.config.s3['cloudfront'] + result.Key;
        } catch (e) {
            throw e;
            this.ctx.app.logger.error(`uploadImage CATCH ERROR：${e ? e.message : e}`);
            return ResponseUtil.resError(e.message, 500);
        }
    }

    async uploadPublicFile(prefix) {
        try {

            let files = this.ctx.request.files;

            if (!files || !(Array.isArray(files)) || !files[0].filepath) {
                return ResponseUtil.retArgErr();
            }
            let filepath = files[0].filepath;
            let filename = files[0].filename;
            let mime = files[0].mime;
            if (!mime) {
                mime = files[0].mimeType;
            }
            let name = this.__getFileName(prefix, filename,filepath);
            let result = await this._uploadImagePublicFun(filepath, name, mime);
            return this.app.config.s3['cloudfront-public'] + result.Key;
        } catch (e) {
            throw e;
            this.ctx.app.logger.error(`uploadImage CATCH ERROR：${e ? e.message : e}`);
            return ResponseUtil.resError(e.message, 500);
        }
    }

    async uploadPublicFileByS3(filePath,fileName,mime){
        try{
            let result = await this._uploadImagePublicFun(filePath, fileName, mime);
            return this.app.config.s3['cloudfront-public'] + result.Key;
        }catch (e) {
            throw e;
            this.ctx.app.logger.error(`uploadPublicFileByS3 ERROR：${e ? e.message : e}`);
        }
    }

    async isExistPublicObjectByS3(key){
        let self = this;
        return new Promise(function (resolve, reject) {
            let s3 = self.getS3ClientPublic();
            let params = {
                Bucket: self.app.config.s3['bucket-name-public'],
                Key: key
            };
            s3.headObject(params,function (err,data) {
                console.error(err,data,key)
                resolve(data?true:false)
            })
        });
    }


    async uploadLocalFile(filepath, prefix, mime) {
        try {
            if (!prefix) {
                return ResponseUtil.retArgErr();
            }
            if (!filepath) {
                return ResponseUtil.retArgErr();
            }
            let suffix = filepath.substring(filepath.lastIndexOf("."));
            let name = prefix + "/" + moment().format('YYYY-MM-DD') + "-" + StringUtil.getUUID() + suffix;

            let result = await this._uploadImageFun(filepath, name, mime);
            console.log(result);
            return result.Key;
        } catch (e) {
            throw e;
            this.ctx.app.logger.error(`uploadLocalFile CATCH ERROR：${e ? e.message : e}`);
            return ResponseUtil.resError(e.message, 500);
        }
    }

    async __getSignedUrl(prefix) {
        let self = this;
        let s3 = this.getS3Client();
        return new Promise(function (resolve, reject) {
            let name = prefix + "/" + new Date().getTime() + StringUtil.getUUID().slice(0, 9);
            let params = {Bucket: self.app.config.s3['bucket-name'], Key: name, Expires: 60 * 5};
            s3.getSignedUrl('putObject', params, function (err, url) {
                console.log('Signed URL: ' + url);
                resolve(url);
            });
        });
    }

    async getSignedUrl(prefix) {
        let result = await this.__getSignedUrl(prefix);
        return result;
    }

    /**
     * 根据key访问私有链接
     * @param key
     * @returns {Promise<void>}
     */
    async getPreSignatureUrl(key) {
        let self = this;
        let s3 = this.getS3Client();
        return new Promise(function (resolve, reject) {
            let params = {
                Bucket: self.app.config.s3['bucket-name'],
                Key: key,
                Expires: 60 * 1   //1 minutes
            };
            s3.getSignedUrl('getObject', params, function (err, url) {
                if (err) {
                    reject(err)
                } else {
                    resolve(url)
                }
            })
        })
    }


    async uploadOSSFile() {
        let files = this.ctx.request.files;

        if (!files || !(Array.isArray(files)) || !files[0].filepath) {
            return ResponseUtil.retArgErr();
        }

        let file = files[0];
        let filepath = files[0].filepath;

        let fileName = StringUtil.getUUID();

        if (["png", "jpg", "jpeg", "gif"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'image/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["mp4", "wav", "avi"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'video/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["zip", "rar", "7z"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'archive/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["pdf"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'document/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }

        let url = await cos.uploadFile(filepath, fileName);
        return url;
    }


    async uploadPrivateOSSFile(){
        let files = this.ctx.request.files;

        if (!files || !(Array.isArray(files)) || !files[0].filepath) {
            return ResponseUtil.retArgErr();
        }

        let file = files[0];
        let filepath = files[0].filepath;

        let mime = files[0].mime;
        if (!mime) {
            mime = files[0].mimeType;
        }

        let fileName = StringUtil.getUUID();

        if (["png", "jpg", "jpeg", "gif","webp"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'image/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["mp4", "wav", "avi"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'video/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["zip", "rar", "7z"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'archive/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        if (["pdf"].includes(file.filepath.split(".").slice(-1)[0])) {
            fileName = 'document/' + fileName + "." + file.filepath.split(".").slice(-1)[0]
        }
        console.log(fileName)
        let url = await cos.uploadPrivateFile(filepath, fileName,mime);
        return url;
    }


    async getSignatureUrl(){
        let url = this.ctx.query.url;
        if(!url){
            return null;
        }

        let key = url.split('.com/')[1];

        let signUrl = await cos.signatureUrl(key);
        return signUrl;
    }


    async uploadOSSLocalFile(filepath, fex) {
        let fileName = StringUtil.getUUID();
        if (["pdf"].includes(filepath.split(".").slice(-1)[0])) {
            fileName = 'sign/' + fileName + "." + filepath.split(".").slice(-1)[0]
        }
        let url = await cos.uploadFile(filepath, fileName);
        return url;
    }


}

module.exports = UploadService;
